package app.web.admin.service.impl;

import app.config.Config;
import app.core.VerificationCode;
import app.core.admin.Admins;
import app.web.admin.domain.ao.LoginAo;
import app.web.admin.domain.ao.PermissionMenusAo;
import app.web.admin.domain.ao.UserCreateAo;
import app.web.admin.domain.ao.UserPatchByIdAo;
import app.web.admin.domain.pojo.Admin;
import app.web.admin.domain.vo.MenuVo;
import app.web.admin.mapper.AdminMapper;
import app.web.admin.mapper.AdminMenuMapper;
import app.web.admin.service.AdminOfRoleService;
import app.web.admin.service.AdminService;
import cn.dev33.satoken.stp.StpUtil;
import com.gitee.feizns.dynamic.tree.Trees;
import com.gitee.feizns.quickstart.easy.captcha.EasyCaptcha;
import com.gitee.feizns.quickstart.spring.AppUtils;
import com.gitee.feizns.quickstart.web.WebUtils;
import com.gitee.feizns.quickstart.web.ex.ServiceException;
import com.gitee.feizns.quickstart.web.restful.Rests;
import com.wf.captcha.SpecCaptcha;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 管理员服务实现
 * @author feizns
 * @since 2025-04-09
 */
@Service
@RequiredArgsConstructor
public class AdminServiceImpl implements AdminService {

    /**
     * 管理员 Mapper
     */
    private final AdminMapper mapper;

    /**
     * 角色 Service 用户
     */
    private final AdminOfRoleService userOfRoleService;

    @Override
    public String loginCaptcha() {
        SpecCaptcha captcha = EasyCaptcha.spec();
        VerificationCode.put(WebUtils.getReq().getSession().getId(), captcha.text().toLowerCase());
        return captcha.toBase64();
    }

    @Override
    public String login(LoginAo ao) {
        //密码编码
        ao.setPassword(Config.passwordEncoder().encode(ao.getPassword()));
        if ( Config.loginCaptchaEnabled() ) {
            if ( !StringUtils.hasText(ao.getCode()) )
                throw new ServiceException("验证码不能为空.");
            VerificationCode.verify(WebUtils.getReq().getSession().getId(), ao.getCode().toLowerCase());
        }
        //根据手机号和密码查询用户
        Admin admin = AdminMapper.findByMobileAndPassword(ao.getMobile(), ao.getPassword());
        if ( admin == null )
            throw new ServiceException("账号或密码错误");
        //登录记录会话
        StpUtil.login(admin.getId());
        //返回token
        return StpUtil.getTokenValue();
    }

    @Override
    public void logout() {
        StpUtil.logout();
    }

    @Override
    public Admin userinfo() {
        return Rests.getById(Admin.class, StpUtil.getLoginIdAsLong());
    }

    @Override
    public Admin create(UserCreateAo ao) {
        //密码编码
        ao.setPassword(Config.passwordEncoder().encode(ao.getPassword()));
        //新增用户
        Admin admin = Rests.create(Admin.class, ao);
        //重置指定用户的角色列表
        userOfRoleService.resetRoleIdsToUser(ao.getRoleIds(), admin.getId());
        return admin;
    }

    @Override
    public Admin patchById(Long id, UserPatchByIdAo ao) {
        //密码编码
        if ( StringUtils.hasText(ao.getPassword()) )
            ao.setPassword(Config.passwordEncoder().encode(ao.getPassword()));
        //更新用户信息
        Admin admin = Rests.patchById(ao.copyPropertiesTo(Admin.class), id);
        //重置指定用户的角色列表
        if ( ao.getRoleIds() != null )
            userOfRoleService.resetRoleIdsToUser(ao.getRoleIds(), id);
        return admin;
    }

    @Override
    public Admin deleteById(Long id) {
        //删除指定用户的角色列表
        userOfRoleService.deleteByUserId(id);
        return Rests.deleteById(Admin.class, id);
    }

    @Override
    public List<MenuVo> permissionMenus(PermissionMenusAo ao) {
        //确认查询的角色
        List<Long> roleIds = ao.getRoleIds() == null ? Admins.current().getRoleIds() : ao.getRoleIds();
        //查询的标识
        List<String> identifiers = AppUtils.getBean(AdminMenuMapper.class).identifiersByRoleIds(roleIds);
        //菜单Map
        Map<Long, MenuVo> menusMap = AdminMenuMapper.all(MenuVo.class).stream().collect(Collectors.toMap(MenuVo::getId, Function.identity()));
        Set<Long> resultIds = new LinkedHashSet<>();
        for (MenuVo menu : menusMap.values()) {
            //匹配期望查询的标识的子菜单
            if ( Admins.vagueAnyMatch(identifiers, menu.getIdentifier()) ) {
                resultIds.add(menu.getId());
                //添加对应父级菜单（用于构建常规从根出发的树形结构）
                do {
                    MenuVo parent = menusMap.get(menu.getParentId());
                    if ( parent != null )
                        resultIds.add(parent.getId());
                    menu = parent;
                } while ( menu != null );
            }
        }
        List<MenuVo> vos = resultIds.stream().map(menusMap::get).filter(Objects::nonNull).sorted(Comparator.comparing(MenuVo::getSort)).toList();
        return Trees.build(vos);
    }

}
